home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / tcsh / dist / sh.exp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-21  |  13.7 KB  |  716 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.01/RCS/sh.exp.c,v 3.5 1991/11/11 01:56:34 christos Exp $ */
  2. /*
  3.  * sh.exp.c: Expression evaluations
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "sh.h"
  38.  
  39. RCSID("$Id: sh.exp.c,v 3.5 1991/11/11 01:56:34 christos Exp $")
  40.  
  41. /*
  42.  * C shell
  43.  */
  44.  
  45. #define IGNORE    1    /* in ignore, it means to ignore value, just parse */
  46. #define NOGLOB    2    /* in ignore, it means not to globone */
  47.  
  48. #define    ADDOP    1
  49. #define    MULOP    2
  50. #define    EQOP    4
  51. #define    RELOP    8
  52. #define    RESTOP    16
  53. #define    ANYOP    31
  54.  
  55. #define    EQEQ    1
  56. #define    GTR    2
  57. #define    LSS    4
  58. #define    NOTEQ    6
  59. #define EQMATCH 7
  60. #define NOTEQMATCH 8
  61.  
  62. static    int     exp1    __P((Char ***, bool));
  63. static    int     exp2    __P((Char ***, bool));
  64. static    int     exp2a    __P((Char ***, bool));
  65. static    int     exp2b    __P((Char ***, bool));
  66. static    int     exp2c    __P((Char ***, bool));
  67. static    Char     *exp3    __P((Char ***, bool));
  68. static    Char     *exp3a    __P((Char ***, bool));
  69. static    Char     *exp4    __P((Char ***, bool));
  70. static    Char     *exp5    __P((Char ***, bool));
  71. static    Char     *exp6    __P((Char ***, bool));
  72. static    void     evalav    __P((Char **));
  73. static    int     isa    __P((Char *, int));
  74. static    int     egetn    __P((Char *));
  75.  
  76. #ifdef EDEBUG
  77. static    void     etracc    __P((char *, Char *, Char ***));
  78. static    void     etraci    __P((char *, int, Char ***));
  79. #endif
  80.  
  81. int
  82. expr(vp)
  83.     register Char ***vp;
  84. {
  85.     return (exp0(vp, 0));
  86. }
  87.  
  88. int
  89. exp0(vp, ignore)
  90.     register Char ***vp;
  91.     bool    ignore;
  92. {
  93.     register int p1 = exp1(vp, ignore);
  94.  
  95. #ifdef EDEBUG
  96.     etraci("exp0 p1", p1, vp);
  97. #endif
  98.     if (**vp && eq(**vp, STRor2)) {
  99.     register int p2;
  100.  
  101.     (*vp)++;
  102.     p2 = exp0(vp, (ignore & IGNORE) || p1);
  103. #ifdef EDEBUG
  104.     etraci("exp0 p2", p2, vp);
  105. #endif
  106.     return (p1 || p2);
  107.     }
  108.     return (p1);
  109. }
  110.  
  111. static int
  112. exp1(vp, ignore)
  113.     register Char ***vp;
  114.     bool    ignore;
  115. {
  116.     register int p1 = exp2(vp, ignore);
  117.  
  118. #ifdef EDEBUG
  119.     etraci("exp1 p1", p1, vp);
  120. #endif
  121.     if (**vp && eq(**vp, STRand2)) {
  122.     register int p2;
  123.  
  124.     (*vp)++;
  125.     p2 = exp1(vp, (ignore & IGNORE) || !p1);
  126. #ifdef EDEBUG
  127.     etraci("exp1 p2", p2, vp);
  128. #endif
  129.     return (p1 && p2);
  130.     }
  131.     return (p1);
  132. }
  133.  
  134. static int
  135. exp2(vp, ignore)
  136.     register Char ***vp;
  137.     bool    ignore;
  138. {
  139.     register int p1 = exp2a(vp, ignore);
  140.  
  141. #ifdef EDEBUG
  142.     etraci("exp3 p1", p1, vp);
  143. #endif
  144.     if (**vp && eq(**vp, STRor)) {
  145.     register int p2;
  146.  
  147.     (*vp)++;
  148.     p2 = exp2(vp, ignore);
  149. #ifdef EDEBUG
  150.     etraci("exp3 p2", p2, vp);
  151. #endif
  152.     return (p1 | p2);
  153.     }
  154.     return (p1);
  155. }
  156.  
  157. static int
  158. exp2a(vp, ignore)
  159.     register Char ***vp;
  160.     bool    ignore;
  161. {
  162.     register int p1 = exp2b(vp, ignore);
  163.  
  164. #ifdef EDEBUG
  165.     etraci("exp2a p1", p1, vp);
  166. #endif
  167.     if (**vp && eq(**vp, STRcaret)) {
  168.     register int p2;
  169.  
  170.     (*vp)++;
  171.     p2 = exp2a(vp, ignore);
  172. #ifdef EDEBUG
  173.     etraci("exp2a p2", p2, vp);
  174. #endif
  175.     return (p1 ^ p2);
  176.     }
  177.     return (p1);
  178. }
  179.  
  180. static int
  181. exp2b(vp, ignore)
  182.     register Char ***vp;
  183.     bool    ignore;
  184. {
  185.     register int p1 = exp2c(vp, ignore);
  186.  
  187. #ifdef EDEBUG
  188.     etraci("exp2b p1", p1, vp);
  189. #endif
  190.     if (**vp && eq(**vp, STRand)) {
  191.     register int p2;
  192.  
  193.     (*vp)++;
  194.     p2 = exp2b(vp, ignore);
  195. #ifdef EDEBUG
  196.     etraci("exp2b p2", p2, vp);
  197. #endif
  198.     return (p1 & p2);
  199.     }
  200.     return (p1);
  201. }
  202.  
  203. static int
  204. exp2c(vp, ignore)
  205.     register Char ***vp;
  206.     bool    ignore;
  207. {
  208.     register Char *p1 = exp3(vp, ignore);
  209.     register Char *p2;
  210.     register int i;
  211.  
  212. #ifdef EDEBUG
  213.     etracc("exp2c p1", p1, vp);
  214. #endif
  215.     if (i = isa(**vp, EQOP)) {
  216.     (*vp)++;
  217.     if (i == EQMATCH || i == NOTEQMATCH)
  218.         ignore |= NOGLOB;
  219.     p2 = exp3(vp, ignore);
  220. #ifdef EDEBUG
  221.     etracc("exp2c p2", p2, vp);
  222. #endif
  223.     if (!(ignore & IGNORE))
  224.         switch (i) {
  225.  
  226.         case EQEQ:
  227.         i = eq(p1, p2);
  228.         break;
  229.  
  230.         case NOTEQ:
  231.         i = !eq(p1, p2);
  232.         break;
  233.  
  234.         case EQMATCH:
  235.         i = Gmatch(p1, p2);
  236.         break;
  237.  
  238.         case NOTEQMATCH:
  239.         i = !Gmatch(p1, p2);
  240.         break;
  241.         }
  242.     xfree((ptr_t) p1);
  243.     xfree((ptr_t) p2);
  244.     return (i);
  245.     }
  246.     i = egetn(p1);
  247.     xfree((ptr_t) p1);
  248.     return (i);
  249. }
  250.  
  251. static Char *
  252. exp3(vp, ignore)
  253.     register Char ***vp;
  254.     bool    ignore;
  255. {
  256.     register Char *p1, *p2;
  257.     register int i;
  258.  
  259.     p1 = exp3a(vp, ignore);
  260. #ifdef EDEBUG
  261.     etracc("exp3 p1", p1, vp);
  262. #endif
  263.     if (i = isa(**vp, RELOP)) {
  264.     (*vp)++;
  265.     if (**vp && eq(**vp, STRequal))
  266.         i |= 1, (*vp)++;
  267.     p2 = exp3(vp, ignore);
  268. #ifdef EDEBUG
  269.     etracc("exp3 p2", p2, vp);
  270. #endif
  271.     if (!(ignore & IGNORE))
  272.         switch (i) {
  273.  
  274.         case GTR:
  275.         i = egetn(p1) > egetn(p2);
  276.         break;
  277.  
  278.         case GTR | 1:
  279.         i = egetn(p1) >= egetn(p2);
  280.         break;
  281.  
  282.         case LSS:
  283.         i = egetn(p1) < egetn(p2);
  284.         break;
  285.  
  286.         case LSS | 1:
  287.         i = egetn(p1) <= egetn(p2);
  288.         break;
  289.         }
  290.     xfree((ptr_t) p1);
  291.     xfree((ptr_t) p2);
  292.     return (putn(i));
  293.     }
  294.     return (p1);
  295. }
  296.  
  297. static Char *
  298. exp3a(vp, ignore)
  299.     register Char ***vp;
  300.     bool    ignore;
  301. {
  302.     register Char *p1, *p2, *op;
  303.     register int i;
  304.  
  305.     p1 = exp4(vp, ignore);
  306. #ifdef EDEBUG
  307.     etracc("exp3a p1", p1, vp);
  308. #endif
  309.     op = **vp;
  310.     if (op && any("<>", op[0]) && op[0] == op[1]) {
  311.     (*vp)++;
  312.     p2 = exp3a(vp, ignore);
  313. #ifdef EDEBUG
  314.     etracc("exp3a p2", p2, vp);
  315. #endif
  316.     if (op[0] == '<')
  317.         i = egetn(p1) << egetn(p2);
  318.     else
  319.         i = egetn(p1) >> egetn(p2);
  320.     xfree((ptr_t) p1);
  321.     xfree((ptr_t) p2);
  322.     return (putn(i));
  323.     }
  324.     return (p1);
  325. }
  326.  
  327. static Char *
  328. exp4(vp, ignore)
  329.     register Char ***vp;
  330.     bool    ignore;
  331. {
  332.     register Char *p1, *p2;
  333.     register int i = 0;
  334.  
  335.     p1 = exp5(vp, ignore);
  336. #ifdef EDEBUG
  337.     etracc("exp4 p1", p1, vp);
  338. #endif
  339.     if (isa(**vp, ADDOP)) {
  340.     register Char *op = *(*vp)++;
  341.  
  342.     p2 = exp4(vp, ignore);
  343. #ifdef EDEBUG
  344.     etracc("exp4 p2", p2, vp);
  345. #endif
  346.     if (!(ignore & IGNORE))
  347.         switch (op[0]) {
  348.  
  349.         case '+':
  350.         i = egetn(p1) + egetn(p2);
  351.         break;
  352.  
  353.         case '-':
  354.         i = egetn(p1) - egetn(p2);
  355.         break;
  356.         }
  357.     xfree((ptr_t) p1);
  358.     xfree((ptr_t) p2);
  359.     return (putn(i));
  360.     }
  361.     return (p1);
  362. }
  363.  
  364. static Char *
  365. exp5(vp, ignore)
  366.     register Char ***vp;
  367.     bool    ignore;
  368. {
  369.     register Char *p1, *p2;
  370.     register int i = 0;
  371.  
  372.     p1 = exp6(vp, ignore);
  373. #ifdef EDEBUG
  374.     etracc("exp5 p1", p1, vp);
  375. #endif
  376.     if (isa(**vp, MULOP)) {
  377.     register Char *op = *(*vp)++;
  378.  
  379.     p2 = exp5(vp, ignore);
  380. #ifdef EDEBUG
  381.     etracc("exp5 p2", p2, vp);
  382. #endif
  383.     if (!(ignore & IGNORE))
  384.         switch (op[0]) {
  385.  
  386.         case '*':
  387.         i = egetn(p1) * egetn(p2);
  388.         break;
  389.  
  390.         case '/':
  391.         i = egetn(p2);
  392.         if (i == 0)
  393.             stderror(ERR_DIV0);
  394.         i = egetn(p1) / i;
  395.         break;
  396.  
  397.         case '%':
  398.         i = egetn(p2);
  399.         if (i == 0)
  400.             stderror(ERR_MOD0);
  401.         i = egetn(p1) % i;
  402.         break;
  403.         }
  404.     xfree((ptr_t) p1);
  405.     xfree((ptr_t) p2);
  406.     return (putn(i));
  407.     }
  408.     return (p1);
  409. }
  410.  
  411. static Char *
  412. exp6(vp, ignore)
  413.     register Char ***vp;
  414.     bool    ignore;
  415. {
  416.     int     ccode, i = 0;
  417.     register Char *cp, *dp, *ep;
  418.  
  419.     if (**vp == 0)
  420.     stderror(ERR_NAME | ERR_EXPRESSION);
  421.     if (eq(**vp, STRbang)) {
  422.     (*vp)++;
  423.     cp = exp6(vp, ignore);
  424. #ifdef EDEBUG
  425.     etracc("exp6 ! cp", cp, vp);
  426. #endif
  427.     i = egetn(cp);
  428.     xfree((ptr_t) cp);
  429.     return (putn(!i));
  430.     }
  431.     if (eq(**vp, STRtilde)) {
  432.     (*vp)++;
  433.     cp = exp6(vp, ignore);
  434. #ifdef EDEBUG
  435.     etracc("exp6 ~ cp", cp, vp);
  436. #endif
  437.     i = egetn(cp);
  438.     xfree((ptr_t) cp);
  439.     return (putn(~i));
  440.     }
  441.     if (eq(**vp, STRLparen)) {
  442.     (*vp)++;
  443.     ccode = exp0(vp, ignore);
  444. #ifdef EDEBUG
  445.     etraci("exp6 () ccode", ccode, vp);
  446. #endif
  447.     if (*vp == 0 || **vp == 0 || ***vp != ')')
  448.         stderror(ERR_NAME | ERR_EXPRESSION);
  449.     (*vp)++;
  450.     return (putn(ccode));
  451.     }
  452.     if (eq(**vp, STRLbrace)) {
  453.     register Char **v;
  454.     struct command faket;
  455.     Char   *fakecom[2];
  456.  
  457.     faket.t_dtyp = NODE_COMMAND;
  458.     faket.t_dflg = 0;
  459.     faket.t_dcar = faket.t_dcdr = faket.t_dspr = NULL;
  460.     faket.t_dcom = fakecom;
  461.     fakecom[0] = STRfakecom;
  462.     fakecom[1] = NULL;
  463.     (*vp)++;
  464.     v = *vp;
  465.     for (;;) {
  466.         if (!**vp)
  467.         stderror(ERR_NAME | ERR_MISSING, '}');
  468.         if (eq(*(*vp)++, STRRbrace))
  469.         break;
  470.     }
  471.     if (ignore & IGNORE)
  472.         return (Strsave(STRNULL));
  473.     psavejob();
  474.     if (pfork(&faket, -1) == 0) {
  475.         *--(*vp) = 0;
  476.         evalav(v);
  477.         exitstat();
  478.     }
  479.     pwait();
  480.     prestjob();
  481. #ifdef EDEBUG
  482.     etraci("exp6 {} status", egetn(value(STRstatus)), vp);
  483. #endif
  484.     return (putn(egetn(value(STRstatus)) == 0));
  485.     }
  486.     if (isa(**vp, ANYOP))
  487.     return (Strsave(STRNULL));
  488.     cp = *(*vp)++;
  489.     if (*cp == '-' && any("erwxfdzoplst", cp[1])) {
  490.     struct stat stb;
  491.  
  492.     if (cp[2] != '\0')
  493.         stderror(ERR_NAME | ERR_FILEINQ);
  494.     /*
  495.      * Detect missing file names by checking for operator in the file name
  496.      * position.  However, if an operator name appears there, we must make
  497.      * sure that there's no file by that name (e.g., "/") before announcing
  498.      * an error.  Even this check isn't quite right, since it doesn't take
  499.      * globbing into account.
  500.      */
  501.     if (isa(**vp, ANYOP) && stat(short2str(**vp), &stb))
  502.         stderror(ERR_NAME | ERR_FILENAME);
  503.  
  504.     dp = *(*vp)++;
  505.     if (ignore & IGNORE)
  506.         return (Strsave(STRNULL));
  507.     ep = globone(dp, G_ERROR);
  508.     switch (cp[1]) {
  509.  
  510.     case 'r':
  511.         i = !access(short2str(ep), R_OK);
  512.         break;
  513.  
  514.     case 'w':
  515.         i = !access(short2str(ep), W_OK);
  516.         break;
  517.  
  518.     case 'x':
  519.         i = !access(short2str(ep), X_OK);
  520.         break;
  521.  
  522.     case 't':    /* SGI extension, true when file is a tty */
  523.         {
  524.         int fd;
  525.  
  526.         if ((fd = open(short2str(ep), O_RDONLY)) == -1)
  527.             i = 0;
  528.         else {
  529.             i = isatty(fd);
  530.             (void) close(fd);
  531.         }
  532.         }
  533.         break;
  534.  
  535.     default:
  536.         if (
  537. #ifdef S_IFLNK
  538.         cp[1] == 'l' ? lstat(short2str(ep), &stb) :
  539. #endif
  540.         stat(short2str(ep), &stb)) {
  541.         xfree((ptr_t) ep);
  542.         return (Strsave(STR0));
  543.         }
  544.         switch (cp[1]) {
  545.  
  546.         case 'f':
  547.         i = S_ISREG(stb.st_mode);
  548.         break;
  549.  
  550.         case 'd':
  551.         i = S_ISDIR(stb.st_mode);
  552.         break;
  553.  
  554.         case 'p':
  555. #ifdef S_ISFIFO
  556.         i = S_ISFIFO(stb.st_mode);
  557. #else
  558.         i = 0;
  559. #endif
  560.         break;
  561.  
  562.         case 'l':
  563. #ifdef S_ISLNK
  564.         i = S_ISLNK(stb.st_mode);
  565. #else
  566.         i = 0;
  567. #endif
  568.         break;
  569.  
  570.         case 's':
  571. #ifdef S_ISSOCK
  572.         i = S_ISSOCK(stb.st_mode);
  573. #else
  574.         i = 0;
  575. #endif
  576.         break;
  577.  
  578.         case 'z':
  579.         i = stb.st_size == 0;
  580.         break;
  581.  
  582.         case 'e':
  583.         i = 1;
  584.         break;
  585.  
  586.         case 'o':
  587.         i = stb.st_uid == uid;
  588.         break;
  589.         }
  590.     }
  591. #ifdef EDEBUG
  592.     etraci("exp6 -? i", i, vp);
  593. #endif
  594.     xfree((ptr_t) ep);
  595.     return (putn(i));
  596.     }
  597. #ifdef EDEBUG
  598.     etracc("exp6 default", cp, vp);
  599. #endif
  600.     return (ignore & NOGLOB ? Strsave(cp) : globone(cp, G_ERROR));
  601. }
  602.  
  603. static void
  604. evalav(v)
  605.     register Char **v;
  606. {
  607.     struct wordent paraml1;
  608.     register struct wordent *hp = ¶ml1;
  609.     struct command *t;
  610.     register struct wordent *wdp = hp;
  611.  
  612.     set(STRstatus, Strsave(STR0));
  613.     hp->prev = hp->next = hp;
  614.     hp->word = STRNULL;
  615.     while (*v) {
  616.     register struct wordent *new =
  617.     (struct wordent *) xcalloc(1, sizeof *wdp);
  618.  
  619.     new->prev = wdp;
  620.     new->next = hp;
  621.     wdp->next = new;
  622.     wdp = new;
  623.     wdp->word = Strsave(*v++);
  624.     }
  625.     hp->prev = wdp;
  626.     alias(¶ml1);
  627.     t = syntax(paraml1.next, ¶ml1, 0);
  628.     if (seterr)
  629.     stderror(ERR_OLD);
  630.     execute(t, -1, NULL, NULL);
  631.     freelex(¶ml1), freesyn(t);
  632. }
  633.  
  634. static int
  635. isa(cp, what)
  636.     register Char *cp;
  637.     register int what;
  638. {
  639.     if (cp == 0)
  640.     return ((what & RESTOP) != 0);
  641.     if (cp[1] == 0) {
  642.     if (what & ADDOP && (*cp == '+' || *cp == '-'))
  643.         return (1);
  644.     if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%'))
  645.         return (1);
  646.     if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' ||
  647.                   *cp == '~' || *cp == '^' || *cp == '"'))
  648.         return (1);
  649.     }
  650.     else if (cp[2] == 0) {
  651.     if (what & RESTOP) {
  652.         if (cp[0] == '|' && cp[1] == '&')
  653.         return (1);
  654.         if (cp[0] == '<' && cp[1] == '<')
  655.         return (1);
  656.         if (cp[0] == '>' && cp[1] == '>')
  657.         return (1);
  658.     }
  659.     if (what & EQOP) {
  660.         if (cp[0] == '=') {
  661.         if (cp[1] == '=')
  662.             return (EQEQ);
  663.         if (cp[1] == '~')
  664.             return (EQMATCH);
  665.         }
  666.         else if (cp[0] == '!') {
  667.         if (cp[1] == '=')
  668.             return (NOTEQ);
  669.         if (cp[1] == '~')
  670.             return (NOTEQMATCH);
  671.         }
  672.     }
  673.     }
  674.     if (what & RELOP) {
  675.     if (*cp == '<')
  676.         return (LSS);
  677.     if (*cp == '>')
  678.         return (GTR);
  679.     }
  680.     return (0);
  681. }
  682.  
  683. static int
  684. egetn(cp)
  685.     register Char *cp;
  686. {
  687.     if (*cp && *cp != '-' && !Isdigit(*cp))
  688.     stderror(ERR_NAME | ERR_EXPRESSION);
  689.     return (getn(cp));
  690. }
  691.  
  692. /* Phew! */
  693.  
  694. #ifdef EDEBUG
  695. static void
  696. etraci(str, i, vp)
  697.     char   *str;
  698.     int     i;
  699.     Char ***vp;
  700. {
  701.     xprintf("%s=%d\t", str, i);
  702.     blkpr(*vp);
  703.     xprintf("\n");
  704. }
  705. static void
  706. etracc(str, cp, vp)
  707.     char   *str;
  708.     Char   *cp;
  709.     Char ***vp;
  710. {
  711.     xprintf("%s=%s\t", str, cp);
  712.     blkpr(*vp);
  713.     xprintf("\n");
  714. }
  715. #endif
  716.